package ltd.dujiabao.capability.adapter.driven.persistence.capmng;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import ltd.dujiabao.capability.common.dto.ErrorCodes;
import ltd.dujiabao.capability.common.exception.BusinessException;
import ltd.dujiabao.capability.common.utils.DateUtils;
import ltd.dujiabao.capability.common.utils.JsonUtils;
import ltd.dujiabao.capability.domain.capmng.cap.Capability;
import ltd.dujiabao.capability.domain.capmng.cap.CapabilityIdentity;
import ltd.dujiabao.capability.domain.capmng.cap.CapabilityRepository;

/**
 * @author : DuJiabao
 * @Project : ddd-capability
 * @Time : 2024/4/6 23:13
 * @Desc :
 */
@Repository
public class CapabilityRepositoryImpl implements CapabilityRepository {
    @Autowired
    private CapabilityDAO capabilityDAO;

    private Cache<CapabilityIdentity, Capability> cache;

    @PostConstruct
    public void init() {
        cache = CacheBuilder.newBuilder()
                .maximumSize(8000)
                .build();
    }

    @Override
    public boolean exists(CapabilityIdentity identity) {
        return capabilityDAO.existsAllByDevModelIdAndHardwareVerAndFirmwareVer(
                identity.getDevModelId(), identity.getHardwareVer(), identity.getFirmwareVer());
    }

    @Override
    public void save(Capability capability) {
        if (capability.isEmpty()) {
            return;
        }

        List<CapabilityDO> dos = new ArrayList<>();
        for (Map.Entry<String, Object> module : capability.getModules().entrySet()) {
            CapabilityDO capabilityDO = new CapabilityDO();
            dos.add(capabilityDO);

            capabilityDO.setDevModelId(capability.getDevModelId())
                    .setHardwareVer(capability.getHardwareVer())
                    .setFirmwareVer(capability.getFirmwareVer())
                    .setModule(module.getKey())
                    .setBody(JsonUtils.bean2Json(module.getValue()))
                    .setCreatedAt(DateUtils.toLongSecond(capability.getCreatedAt()))
                    .setCreatedBy(capability.getCreatedBy())
                    .setLastUpdatedAt(DateUtils.toLongSecond(capability.getLastUpdatedAt()))
                    .setLastUpdatedBy(capabilityDO.getLastUpdatedBy());
        }
        capabilityDAO.saveAll(dos);
        cache.put(capability.getIdentity(), capability);
    }

    @Override
    public Capability findByIdentity(CapabilityIdentity identity) {
        try {
            return cache.get(identity, () -> dbFindByIdentity(identity));
        } catch (ExecutionException e) {
            throw new BusinessException(e, ErrorCodes.SYSTEM_INTERNAL_ERROR.getCode());
        }
    }

    private Capability dbFindByIdentity(CapabilityIdentity identity) {
        List<CapabilityDO> capabilityDos = capabilityDAO.findAllByDevModelIdAndHardwareVerAndFirmwareVer(
                identity.getDevModelId(), identity.getHardwareVer(), identity.getFirmwareVer());
        Capability capability = new Capability(LocalDateTime.now(), 0L, identity.getDevModelId(), identity.getHardwareVer(), identity.getFirmwareVer());
        for (CapabilityDO capabilityDo : capabilityDos) {
            capability.addModule(capabilityDo.getModule(), JsonUtils.json2Map(capabilityDo.getBody()));
        }
        return capability;
    }
}
